<template>
  <div>
    <el-form ref="formRef" :rules="rules" :model="form" label-width="100px">
      <el-form-item label="部门名称" prop="name">
        <!-- 这里面的属性必须都是 form对象里的书写，不能写form之外的书写 -->
        <!-- <el-input v-model="name" /> -->
        <el-input v-model="form.name" />
      </el-form-item>
      <el-form-item label="部门编码" prop="code">
        <el-input v-model="form.code" />
      </el-form-item>
      <el-form-item label="部门负责人" prop="manager">
        <el-select v-model="form.manager" placeholder="请选择活动区域">
          <!-- <el-option label="区域一" value="shanghai" />
          <el-option label="区域二" value="beijing" /> -->
          <el-option v-for="item in userList" :key="item.id" :label="item.username" :value="item.username" />
        </el-select>
      </el-form-item>
      <el-form-item label="部门介绍" prop="introduce">
        <el-input v-model="form.introduce" type="textarea" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">{{ isEdit ? '编辑' : '新增' }}</el-button>
        <!-- dialogVisible = false 不能这样写，dialogVisible 这个值是父组件的值， 应该是通知父组件 -->
        <el-button @click="cancle">取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import { getUserSimpleRequest } from '@/api/employees'
import { addDepartmentRequest, getDeparmentByIdRequest, updateDepartmentByIdRequest } from '@/api/department'

export default {
  name: '',
  props: {
    currentPid: {
      type: String,
      default: ''
    },
    isEdit: {
      type: Boolean,
      default: false
    },
    arrListToChild: {
      type: Array,
      // default: [] //复杂数据类型，不能直接写一个固定的地址，需要通过函数返回一个新地址
      default: () => []
    }
  },
  data() {
    const that = this
    // this值只要有个函数(非箭头函数)，那么函数调用的时候，就会动态创建一个变量，名称叫this
    // console.log('data函数里面的this值：', this)
    // 箭头函数里面没有this值，如果箭头函数里面要访问this值，就会找上一层作用域的this值
    // const validateCode = (rule, value, callback) => {
    const validateCode = function(rule, value, callback) {
      // 因为下面rules规则的 默认几个规则都被我们删除了，全部由自定义校验规则接管
      if (!value) {
        return callback(new Error('code码必填'))
      }
      // 一定要保证this是当前 组件实例对象
      // console.log('校验函数里面的this：', that)
      let codeList = that.arrListToChild.map(item => item.code)

      if (that.isEdit) {
        // 如果是编辑的时候，当前元素的code码，就不能当做重复的数据，因为别人可能就修改一个 介绍，code name都不改变
        // 这种情况下当前的 code就不算重复
        // console.log(111133) // this.currentPid === undefined
        // codeList = that.arrListToChild.filter(item => item.id !== this.currentPid).map(item => item.code)
        // that this 使用的时候不报错， 这种情况下怎么去查找问题，修改bug！！！
        codeList = that.arrListToChild.filter(item => item.id !== that.currentPid).map(item => item.code)
      }
      console.log(codeList)
      // console.log('代码执行了没有', value)

      if (codeList.includes(value)) {
        callback(new Error(`当前value: ${value} 值重复`))
      } else {
        // r如果自定义校验规则 callback函数必须调用，否则 校验不执行
        callback()
      }
    }

    const validatorName = (rule, value, callback) => {
      // const nameList = this.arrListToChild.map(item => item.name)
      // 上面代码，获取所有名称，没用， 我们要去当前你点击的 元素的 所有子元素
      let nameList = this.arrListToChild.filter(item => item.pid === this.currentPid).map(item => item.name)

      if (this.isEdit) {
        // 1.先找当前元素的兄弟， 2. 在过滤掉自己
        // 先找到当前 需要编辑的元素 当前元素  this.currentPid
        const editParent = this.arrListToChild.find(item => item.id === this.currentPid)
        // 再去找 editParent 所有的兄弟元素， 具体的就是 pid都等于 editParent.pid 的元素
        const brother = this.arrListToChild.filter(item => item.pid === editParent.pid)
        // 因为是编辑，所以最后还需要过滤掉当前的 被编辑的元素
        nameList = brother.filter(item => item.id !== this.currentPid).map(item => item.name)
        // console.log(brother)
      }

      console.log(nameList)
      if (nameList.includes(value)) {
        callback(new Error(`当前部门名称: ${value} 已经存在`))
      } else {
        callback()
      }
    }

    return {
      name: '',
      // form对象里面有哪些属性，由后端决定
      // 去后端看接口文档，看别人的接口需要什么参数，我们在来写form的属性名称
      form: {
        name: '',
        code: '',
        manager: '',
        introduce: ''
      },
      userList: [],
      rules: {
        name: [
          // 基础校验
          { required: true, message: '请输入活动名称', trigger: 'blur' },
          { min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' },
          // 自己写一个自定义校验规则，--- 做业务校验
          { validator: validatorName, trigger: 'change' }
        ],
        // 如果要做一些复杂的校验，例如业务校验，去重啥的， 就需要自己写一些 自定义校验规则
        // 类似于登录页面的  手机号的正则校验
        code: [
          // { required: true, message: '请输入活动名称', trigger: 'blur' },
          { min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' },
          { validator: validateCode, trigger: 'blur' }
        ],
        manager: [
          { required: true, message: '请输入活动名称', trigger: 'change' }
        ],
        introduce: [
          { required: true, message: '请输入活动名称', trigger: 'blur' },
          { min: 1, max: 300, message: '长度在 1 到 300 个字符', trigger: 'blur' }
        ]
      }
    }
  },
  // watch: {
  //   currentPid: {
  //     handler: function(newOld, oldVal) {
  //       console.log('监听curretnid的变化：', newOld, oldVal)
  //       this.getDeparmentById()
  //     },
  //     immediate: true, // 组件创建的时候，里面执行一遍watch
  //     deep: true // 加入对象的层级很深， 不加上deep这个属性， 对象子属性的改变，就不会被watch监听到
  //   }
  // },
  created() {
    console.log('这个组件是否创建', this.arrListToChild)
    // 这个里面代码不要写太多，只调用其他的函数即可
    this.getUserSimple()
    // 如果是编辑的时候，就要发起根据id查询数据的接口
    this.getDeparmentById()
  },
  destroyed() {
    console.log('这个组件是否销毁了')
  },
  methods: {
    async getUserSimple() {
      try {
        const res = await getUserSimpleRequest()
        this.userList = res.data
        console.log(res)
      } catch (err) {
        console.log('获取用户基本列表失败', err)
      }
    },
    async getDeparmentById() {
      if (this.isEdit) {
        const res = await getDeparmentByIdRequest(this.currentPid)
        console.log(res)
        this.form = res?.data
      }
    },
    async addDepartment() {
      try {
        // {...this.form, pid: this.currentPid}
        const res = await addDepartmentRequest({ ...this.form, pid: this.currentPid })
        console.log('添加接口返回值：', res)
        // 请求成功以后， 关闭弹出框
        // 应该抛出一个新的事件， 在父组件里面，既要将弹出框关闭，也要重新发请求，获取新的树状结构列表
        // 唉工作里面，有些后端，对于业务成功或者失败的，逻辑是通过一些code码来判断的
        if (res.success) {
          // 如果有任务代码成功，就执行下面的逻辑，和以前业余
          this.$emit('success')
        } else {
          // 如果业务代码失败， 就提示一个错误， 不关闭弹窗，不销毁数据，让用户修改数据了以后，重新提交
          this.$message.error(res.message)
        }
      } catch (err) {
        //
      }
    },
    async updateDepartmentById() {
      const res = await updateDepartmentByIdRequest(this.form)
      if (res.success) {
        this.$emit('success')
      } else {
        this.$message.error(res.message)
      }
    },
    onSubmit() {
      // 因为点击创建，后面还需要做一些校验，这个代码会有很多，所有
      // 我们需要将 新增的接口请求，封装到外面，作为一个函数
      // console.log(this.form)

      // 先校验表单是否 通过，在发请求
      // this.$refs.formRef 这个就是form的组件实例  <el-form ref="formRef">
      // new VueComponent(xxx)  所以我们知道<el-form> 就是一个组件对象
      // 如果<div ref="aaa">  this.$refs.aaa 这就是dom元素
      // console.log(this.$refs.formRef)

      this.$refs.formRef.validate(val => {
        // 如果value为真，表示所有校验通过，否则就有某个校验失败
        // console.log(val)
        if (val) {
          if (this.isEdit) {
            // 如果是编辑就发编辑的请求
            this.updateDepartmentById()
          } else {
            this.addDepartment()
          }
        }
      })
    },
    cancle() {
      this.$emit('MyCloseEvent')
    }
  }
}
</script>
